package com.zhiying.shiro;

import com.zhiying.web.util.HttpServletUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Set;

@Component
public class PermissionHandler extends HandlerInterceptorAdapter {
    private static Logger LOGGER = LoggerFactory.getLogger(PermissionHandler.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            RequestPermission annotation = method.getAnnotation(RequestPermission.class);
            /*没有注解或不拦截，直接通过*/
            if(annotation==null || !annotation.isSecurity()){
                LOGGER.info(HttpServletUtils.getLocalUrl(request)+"===不拦截");
                return true;
            }
            /*认证身份信息*/
            AuthenticationInfo auth = (AuthenticationInfo) HttpServletUtils.getSessionObject(request,"Admin");
            if(null == auth){
                /*session过期或未登录*/
                respData(annotation,"请登录系统",request,response);
            }
            if(null != auth && !getAuthenticationInfo(auth,request)){
                System.out.println("身份认证失败");
                return false;
            }

            /*校验权限*/
            String[] roles = annotation.roles();
            String[] resources = annotation.resource();
            if(roles.length != 0 && resources.length != 0){
                //获取用户权限集合
                AuthorizationInfo author = (AuthorizationInfo) HttpServletUtils.getSessionObject(request,"Authc");
                if(null == author){
                    respData(annotation,"权限不足",request,response);
                }else {
                    Set<String> roleSet = author.getRoles();
                    Set<String> resourceSet = author.getResources();
                    if (!containPermission(roles, resources, roleSet, resourceSet)) {
                        System.out.println("没通过拦截器");
                        return false;
                    }
                }
            }
        }
        return true;
    }


    /**
     * 身份校验
     * @param auth
     * @param request
     * @return
     */
    private boolean getAuthenticationInfo(AuthenticationInfo auth,HttpServletRequest request){
        String username = auth.getUserName();
        String remoteAddr = auth.getRemoteAddr();
        Cookie[] cookies = request.getCookies();
        for(Cookie cookie : cookies){
            if(StringUtils.equals(cookie.getName(),"username")){
                String cacheName = cookie.getValue();
                if(StringUtils.equals(username,cacheName)){
                    String ip = request.getRemoteAddr();
                    if(StringUtils.equals(remoteAddr,ip)){
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * 判断权限
     * @param roles
     * @param resources
     * @param roleSet
     * @param resourceSet
     * @return
     */
    private boolean containPermission(String[] roles, String[] resources, Set<String> roleSet, Set<String> resourceSet) {
        boolean isRole = false;
        boolean isResource = false;
        for(String role : roles){
            if(roleSet.contains(role)){
                isRole = true;
            }
        }
        for(String resource : resources){
            if(resourceSet.contains(resource)){
                isResource = true;
            }
        }
        if(isRole && isResource){
            return true;
        }else{
            return false;
        }

    }

    private void respData(RequestPermission annotation, String msg, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if(ContentType.texthtml.equals(annotation.returnType())){
            request.getRequestDispatcher(annotation.returnURL()).forward(request,response);
        }else if(ContentType.textjson.equals(annotation.returnType())){
            String text = "{\"success\":false,\"msg\":\""+msg+"\"}";
            System.out.println(text);
            //ResponseUtils.renderJson(response,text);
        }
    }
}
